

#include "vector.h"
#include "matrix.h"

#include <math.h>

vm_matrix *vm_minor_matrix2(vm_matrix *mtx, int r, int c);


vm_matrix *vm_adjoint(vm_matrix *mtx){

  if (mtx->rows != mtx->columns) return NULL;

  vm_matrix *adj = vm_make_matrix(mtx->rows, mtx->columns);

  int r, c;
  for ( r = 0; r < mtx->rows; r++)
    for ( c = 0; c < mtx->columns; c++)
      adj->data[r][c] = vm_cofactor(mtx, r, c);

  vm_matrix *trans = vm_transpose(adj);
  vm_free_matrix(adj);

  return trans;

}

double vm_cofactor(vm_matrix *mtx, int r, int c){

  double temp = 0;
  vm_matrix *m = vm_minor_matrix(mtx, r, c);
  vm_determinant(m, &temp);
  vm_free_matrix(m);
  double flip = pow(-1, (c + r));

  if (mtx->columns % 2 == 1) flip = 1;
  return  flip * temp;

}

vm_matrix *_vm_minor_matrix_bu(vm_matrix *mtx, int loc){

  if (mtx->rows != mtx->columns) return NULL;
  if (loc >= mtx->columns) return NULL;

  vm_matrix *minor = vm_make_matrix(mtx->rows - 1, mtx->columns - 1);
  
  int i;
  for ( i = 0; i < mtx->columns - 1; i++){
    int col = (loc + (i+1)) % mtx->columns;
    //printf("[vm_minor_matrix] %d %d %d %d\n", col, i, loc, mtx->columns);
    int j;
    for ( j = 1; j < mtx->rows; j++){
      minor->data[j-1][i] = mtx->data[j][col];
      //printf("[vm_minor_matrix]   %d %d %d %d\n", i, j-1, j, col);
    }
  }

  return minor;

}

vm_matrix *vm_minor_matrix(vm_matrix *mtx, int r, int c){

    if (mtx->rows != mtx->columns) return NULL;
    if (c >= mtx->columns || r >= mtx->rows) return NULL;

    vm_matrix *minor = vm_make_matrix(mtx->rows - 1, mtx->columns - 1);

    int i;
    for ( i = 0; i < mtx->columns - 1; i++){
      int col = (c + (i+1)) % mtx->columns;
      
      int j;
      for ( j = 0; j < mtx->rows - 1; j++){
	int row = (r + (j+1)) % mtx->rows;
	
	minor->data[j][i] = mtx->data[row][col];
      }
    }

    return minor;

}
